package org.tim.robot.fenixos;

import java.util.*;
import java.util.concurrent.*;
import java.net.*;
import java.lang.*;
import java.io.*;

/**
 * Symbolic connection to a host
 * A connection object accepts messages that will be send to the host ASAP
 * <quote>At this moment messages that could not be send, because no connection could be made to the host, are removed from the queue<quote>
 * @author Tim Fennis
 */
public class Connection implements Runnable {
	
	private LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
	
	private Socket s = null;
	private BufferedWriter bw = null;
	private String ip = null;
	private int port = 0;
	
	/**
	 * Create a connection to a specific ip and port number
	 * @param ip The ip address 
	 * @param port The port number
	 */
	public Connection ( String ip , int port ) {
		this.ip = ip;
		this.port = port;
		Thread t = new Thread(this);
		t.start();
	}
	
	/**
	 * Adds a message to the end of the message queue
	 * <p>Messages that could not be send will be removed from the queue</p>
	 * @param message The message to send ( as a string )
	 */
	public void send ( String message ) throws Exception {
		queue.put( message );
	}
	
	/**
	 * Returns the hashcode of this object
	 * the hashcode is the ip addr's  hashcode multiplied by the port number
	 * @return the hashcode
	 */
	public int hashCode ( ) {
		return ip.hashCode() * port;
	}
	
	/**
	 * Check if this object is equal to another object
	 * connection objects are equal if the ip and port number are the same since multiple connections to the same ip and port are imposible
	 * @param o the object to compare to
	 * @return boolean true if equal false if not
	 */
	public boolean equals ( Object o ) {
		
		if ( ! ( o instanceof Connection ) ) {
			return false;
		}
		
		Connection cc = (Connection)o;
		
		if ( cc.ip.equals(this.ip) && cc.port == this.port ) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * The run method for this object
	 */
	public void run ( ) {
		try {
			String focus = null;
			while ( true ) {
				focus = queue.take(); // blocked
				try {
					if ( s == null ) {
						s = new Socket( ip , port );					
					}
					if ( bw == null ) {
						bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
					}
					bw.write( focus );
				} catch ( Exception e ) {
					//todo implement retry meganism..
					//queue.offer( focus );
					s = null;
					focus = null;
				}
			}
		} catch ( Exception e ) {
		
		}
	}
}